package com.sskj.api.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sskj.api.domain.Product;
import com.sskj.api.domain.ProductThingsModel;
import com.sskj.api.domain.ThingModelTemplate;
import com.sskj.api.exception.LogicException;
import com.sskj.api.mapper.ProductMapper;
import com.sskj.api.service.IProductCapabilityMappingService;
import com.sskj.api.service.IProductService;
import com.sskj.api.service.IProductThingsModelService;
import com.sskj.api.vo.req.ProductPageListReq;
import com.sskj.common.constant.RedisConstant;
import com.sskj.common.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Service
public class ProductService extends ServiceImpl<ProductMapper, Product> implements IProductService {

    @Autowired
    private IProductThingsModelService productThingsModelService;

    @Autowired
    private IProductCapabilityMappingService productCapabilityMappingService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private ObjectMapper objectMapper;

    @Override
    @Transactional
    public void add(Product product) {
        LambdaQueryWrapper<Product> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Product::getCategoryId, product.getCategoryId())
                .eq(Product::getName, product.getName());
        if (count(lambdaQueryWrapper) > 0) {
            throw new LogicException("产品已存在");
        }

        product.setCreateTime(LocalDateTime.now());
        if(save(product)) {
            if (product.getCapabilityIds() != null && !product.getCapabilityIds().isEmpty()) {
                productCapabilityMappingService.add(product.getId(), product.getCapabilityIds());
            }
        }
    }

    @Override
    public void update(Product product) {
        LambdaQueryWrapper<Product> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.ne(Product::getId, product.getId())
                .eq(Product::getCategoryId, product.getCategoryId())
                .eq(Product::getName, product.getName());
        if (count(lambdaQueryWrapper) > 0) {
            throw new LogicException("产品已存在");
        }

        product.setCreateTime(LocalDateTime.now());
        updateById(product);

        productCapabilityMappingService.add(product.getId(), product.getCapabilityIds());
    }

    @Override
    public IPage<Product> pageList(ProductPageListReq req) {
        IPage<Product> pageConfig = new Page<>(req.getPageNum(), req.getPageSize());
        IPage<Product> productIPage = baseMapper.pageList(pageConfig, req);

        if (productIPage.getRecords() != null && !productIPage.getRecords().isEmpty()) {
            for (Product product : productIPage.getRecords()) {
                product.setProductCapabilities(productCapabilityMappingService.listCapability(product.getId()));
            }
        }

        return productIPage;
    }

    @Override
    public Product detail(Long id) {
        Product product = baseMapper.detail(id);
        if (product != null) {
            product.setProductCapabilities(productCapabilityMappingService.listCapability(product.getId()));
        }
        return product;
    }

    @Override
    public void bindThingModel(ProductThingsModel productThingsModel) {
        productThingsModelService.add(productThingsModel);
        addOrUpdateThingModelCache(productThingsModel.getProductId());
    }

    @Override
    public void unbindThingModel(long bindId) {
        ProductThingsModel productThingsModel = productThingsModelService.getById(bindId);
        if (productThingsModel != null) {
            productThingsModelService.deleteById(bindId);
            addOrUpdateThingModelCache(productThingsModel.getProductId());
        }
    }

    @Override
    public IPage<ThingModelTemplate> thingModelPageList(long id, long pageNo, long pageSize) {
        return productThingsModelService.pageListByProductId(id, pageNo, pageSize);
    }

    @Override
    public List<ThingModelTemplate> getThingModels(Long id) {
        String key = RedisConstant.DEVICE_THINGS_MODEL + id;
        String cacheData = stringRedisTemplate.opsForValue().get(key);
        List<ThingModelTemplate> thingModelTemplates = new ArrayList<>();
        if (StrUtil.isNotBlank(cacheData)) {
            try {
                thingModelTemplates = objectMapper.readValue(cacheData, new TypeReference<List<ThingModelTemplate>>() {});
            } catch (JsonProcessingException e) {
                log.error("[产品服务]-物模型获取缓存信息反序列化异常。异常信息:{}|缓存信息:{}", e.getMessage(), cacheData);
            }
        } else {
            thingModelTemplates = productThingsModelService.allByProductId(id);
        }
        return thingModelTemplates;
    }

    /**
     * 新增或更新产品物模型缓存
     * @param id 产品ID
     */
    private void addOrUpdateThingModelCache(Long id) {
        List<ThingModelTemplate> thingModelTemplates = productThingsModelService.allByProductId(id);
        String key = RedisConstant.DEVICE_THINGS_MODEL + id;
        if (thingModelTemplates != null && !thingModelTemplates.isEmpty()) {
            try {
                String jsonData = objectMapper.writeValueAsString(thingModelTemplates);
                stringRedisTemplate.opsForValue().set(key, jsonData);
            } catch (JsonProcessingException e) {
                log.error("[产品服务]-物模型缓存异常。异常信息:{}|缓存信息:{}", e.getMessage(),thingModelTemplates);
            }
        } else {
            stringRedisTemplate.delete(key);
        }
    }
}
